#include <windows.h>

#include "time.h"
#include "Randomizer.h"

Randomizer DefaultRandomizer;

#ifdef __cplusplus
extern "C" {

int Random(int min, int max) {
	return (DefaultRandomizer.Random(min, max));
}

}
#endif

const int Randomizer::mag01[2] = { 0, (int)0x9908B0DF };

Randomizer::Randomizer() {
	Generate(time(NULL));
}

Randomizer::Randomizer(int seed) {
	Generate(seed);
}

Randomizer::~Randomizer() {
	// empty
}

void Randomizer::Generate() {
	Generate(time(NULL));
}

void Randomizer::Generate(int seed) {
	DWORD temp1, temp2;
	DWORD index;

	index = 1UL;

	rand_table[0] = seed;

	do {
		rand_table[index] = index + 1812433253 * (rand_table[index - 1] ^ (rand_table[index - 1] >> 30));
		index++;
	}
	while (index < 624);

	index = 0L;
	do {
		temp1 = rand_table[index] ^ rand_table[index + 1];
		++index;
		temp2 = rand_table[index - 1] ^ (temp1 & 0x7FFFFFFF);
		rand_table[index - 1] = rand_table[index + 396] ^ mag01[temp2 & 1] ^ (temp2 >> 1);
	}
	while (index < 227);
	for (; index < 623; rand_table[index - 1] = rand_table[index - 228] ^ mag01[temp2 & 1] ^ (temp2 >> 1)) {
		temp1 = rand_table[index] ^ rand_table[index + 1];
		++index;
		temp2 = rand_table[index - 1] ^ (temp1 & 0x7FFFFFFF);
	}
	index = (rand_table[623] ^ ((rand_table[623] ^ rand_table[0]) & 0x7FFFFFFFu)) >> 1;
	rand_table[623] = index ^ rand_table[396] ^ mag01[(LOBYTE(rand_table[623]) ^ (LOBYTE(rand_table[623]) ^ LOBYTE(rand_table[0]) )) & 1];
	rand_table[624] = 0L;
}

void Randomizer::GenerateState(void) {
	int temp1, temp2;
	DWORD index;

	index = 0;
	do {
		temp1 = rand_table[index] ^ rand_table[index + 1];
		++index;
		temp2 = rand_table[index - 1] ^ (temp1 & 0x7FFFFFFF);
		rand_table[index - 1] = rand_table[index + 396] ^ mag01[temp2 & 1] ^ (temp2 >> 1);
	}
	while (index < 227);
	for (; index < 623; rand_table[index - 1] = rand_table[index - 228] ^ mag01[temp2 & 1] ^ (temp2 >> 1)) {
		temp1 = rand_table[index] ^ rand_table[index + 1];
		++index;
		temp2 = rand_table[index - 1] ^ (temp1 & 0x7FFFFFFF);
	}
	index = (rand_table[623] ^ ((rand_table[0] ^ rand_table[623]) & 0x7FFFFFFFu)) >> 1;
	rand_table[623] = index ^ rand_table[396] ^ mag01[(LOBYTE(rand_table[623]) ^ (LOBYTE(rand_table[0]) ^ LOBYTE(rand_table[623]) )) & 1];
	rand_table[624] = 0L;

}

int Randomizer::Random(int min, int max) {
	int index;
	int temp;

	if (rand_table[624] >= 624) {
		GenerateState();
	}
	index = rand_table[624];
	temp = rand_table[index];
	rand_table[624] = index + 1;
	temp = ((((temp >> 11) ^ temp) & 0xFF3A58AD) << 7) ^ (temp >> 11) ^ temp;
	return (min - ((((temp & 0xFFFFDF8C) << 15) ^ temp ^ ((((temp & 0xFFFFDF8C) << 15) ^ temp) >> 18)) * -2.328306436538696e-10 * (max - min + 1)));
}
